/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.bemanager.codegenerator.actions;


import com.inspur.edp.bef.bemanager.codegenerator.JavaCompCodeNames;
import com.inspur.edp.bef.bemanager.codegenerator.ParameterInfo;
import com.inspur.edp.bef.bemanager.util.CheckInfoUtil;
import com.inspur.edp.bef.bizentity.GspBusinessEntity;
import com.inspur.edp.bef.bizentity.operation.BizActionBase;
import com.inspur.edp.bef.bizentity.operation.BizOperation;
import com.inspur.edp.bef.bizentity.operation.componentbase.BizParameter;
import com.inspur.edp.bef.bizentity.operation.componentbase.BizVoidReturnType;
import com.inspur.edp.bef.bizentity.operation.componentenum.BizCollectionParameterType;
import com.inspur.edp.bef.bizentity.operation.componentenum.BizParameterType;
import com.inspur.edp.bef.bizentity.operation.componentinterface.IBizParameter;
import java.util.Map;

public abstract class JavaBaseActionGenerator extends JavaBaseCompCodeGenerator {

  ///#region 字段和属性
  private final BizActionBase action;
  private final java.util.ArrayList<String> usingList;
  private java.util.LinkedHashMap<String, ParameterInfo> parameters;
  private final java.util.ArrayList<Class> allGenericParamType;
  protected String ReturnTypeName = "VoidActionResult";

  ///#endregion


  ///#region 构造与初始化
  public JavaBaseActionGenerator(GspBusinessEntity be, BizOperation operation, String nameSpace,
      String path) {
    super(be, operation, nameSpace, path);
    action = (BizActionBase) ((operation instanceof BizActionBase) ? operation : null);
    if (action == null) {
      throw new RuntimeException("选择了错误的代码模板生成器");
    }
    usingList = new java.util.ArrayList<String>();
    allGenericParamType = new java.util.ArrayList<Class>();

    ///#region ReturnValue
    if (action.getReturnValue() != null && !(action
        .getReturnValue() instanceof BizVoidReturnType)) {
      JavaGetParameterUsing(action.getReturnValue());
      ReturnTypeName = JavaGetParameterTypeName(action.getReturnValue());
    }

    ///#endregion

    ///#region Parameters
    if (action.getParameters() == null || action.getParameters().getCount() < 1) {
      return;
    }
    parameters = new java.util.LinkedHashMap<String, ParameterInfo>();

    for (Object actionParameter : action.getParameters()) {
      JavaGetParameterUsing((IBizParameter) actionParameter);
      if (parameters.containsKey(((IBizParameter) actionParameter).getParamCode())) {
        throw new RuntimeException(
            "存在重复的参数【" + ((IBizParameter) actionParameter).getParamCode() + "】");
      }
      parameters.put(((IBizParameter) actionParameter).getParamCode(),
          JavaBuildParameterInfo((IBizParameter) actionParameter));
    }

    ///#endregion
  }

  private void JavaGetParameterUsing(IBizParameter param) {
    if (param.getCollectionParameterType() == BizCollectionParameterType.List) {
      JavaAddUsing(JavaCompCodeNames.ArrayListNameSpace);
    }
    if (param.getParameterType() == BizParameterType.DateTime) {
      JavaAddUsing(JavaCompCodeNames.DateNameSpace);
    }
    if (param.getParameterType() == BizParameterType.Decimal) {
      JavaAddUsing(JavaCompCodeNames.BigDecimalNameSpace);
    }
    if (param.getParameterType() == BizParameterType.Custom) {
      JavaAddUsing(param.getClassName());
    }

  }

  private String JavaGetParameterTypeName(IBizParameter param) {
    switch (param.getCollectionParameterType()) {
      case None:
        return GetNoneCollectionParaTypeName(param);
      case List:
        return GetListParaTypeName(param);
      case Array:
        return GetArrayParaTypeName(param);
      default:
        throw new RuntimeException("无效的自定义参数配置【" + param.getParamName() + "】");
    }


  }

  private String GetNoneCollectionParaTypeName(IBizParameter param) {

    switch (param.getParameterType()) {
      case String:
        return "String";
      case Boolean:
        return "Boolean";
      case DateTime:
        return "Date";
      case Decimal:
        return "BigDecimal";
      case Double:
        return "Double";
      case Int32:
        return "Integer";
      case Object:
        return "Object";
      default:
        HandleJavaInfo(param);
        if (CheckInfoUtil.checkNull(param.getClassName())) {
          throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
        }
        int index = param.getClassName().lastIndexOf(".");
        return param.getClassName().substring(index + 1, param.getClassName().length());

//				if (!JavaIsGeneric(param))
//				{
//					return param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1);
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result;
//				}

    }
  }

  private String GetArrayParaTypeName(IBizParameter param) {
    switch (param.getParameterType()) {
      case String:
        return "String[]";
      case Boolean:
        return "Boolean[]";
      case DateTime:
        return "Date[]";
      case Decimal:
        return "BigDecimal[]";
      case Double:
        return "Double[]";
      case Int32:
        return "Integer[]";
      case Object:
        return "Object[]";
      default:
        HandleJavaInfo(param);
        if (CheckInfoUtil.checkNull(param.getClassName())) {
          throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
        }

        int index = param.getClassName().lastIndexOf(".");
        return param.getClassName().substring(index + 1, param.getClassName().length()) + "[]";

//				int index = param.getClassName().lastIndexOf(".", StringComparison.Ordinal);
//				if (!JavaIsGeneric(param))
//				{
//					return param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1) + "[]";
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return result + "[]";
//				}

    }
  }

  private String GetListParaTypeName(IBizParameter param) {
    switch (param.getParameterType()) {
      case String:
        return "ArrayList<String>";
      case Boolean:
        return "ArrayList<Boolean>";
      case DateTime:
        return "ArrayList<Date>";
      case Decimal:
        return "ArrayList<BigDecimal>";
      case Double:
        return "ArrayList<Double>";
      case Int32:
        return "ArrayList<Integer>";
      case Object:
        return "ArrayList<Object>";
      default:
        HandleJavaInfo(param);
        if (CheckInfoUtil.checkNull(param.getClassName())) {
          throw new RuntimeException("当前参数【" + param.getParamName() + "】的JavaClassName属性为空，请完善。");
        }
        int index = param.getClassName().lastIndexOf(".");
        return "ArrayList<" + param.getClassName()
            .substring(index + 1, param.getClassName().length()) + ">";

//				if (!JavaIsGeneric(param))
//				{
//					return "ArrayList<" + param.getClassName().substring(index + 1, index + 1 + param.getClassName().length() - index - 1) + ">";
//				}
//				else
//				{
//					String result = JavaGetGenericExpress(allGenericParamType.get(0));
//					allGenericParamType.clear();
//					return "ArrayList<" + result + ">";
//				}

    }
  }

  private String JavaGetParameterMode(IBizParameter param) {
    switch (param.getMode()) {
      case OUT:
        return "out";
      //TODO 待确认
      case INOUT:
        return "ref";
      default:
        return "";
    }

  }

  private ParameterInfo JavaBuildParameterInfo(IBizParameter param) {
    String typeName = JavaGetParameterTypeName(param);
    String paramMode = JavaGetParameterMode(param);
    ParameterInfo tempVar = new ParameterInfo();
    tempVar.setParamName(param.getParamCode());
    tempVar.setParamType(typeName);
    tempVar.setParameterMode(paramMode);
    return tempVar;
  }

  ///#endregion


  ///#region Using
  @Override
  protected void JavaGenerateExtendUsing(StringBuilder result) {
    result.append(GetImportStr(JavaCompCodeNames.ActionApiNameSpace));
    result.append(GetImportStr(JavaCompCodeNames.BaseNameSpace));
    result.append(GetImportStr(JavaCompCodeNames.ChangesetNameSpace));
    result.append(GetImportStr(JavaCompCodeNames.ContextNameSpace));
    result.append(GetImportStr(JavaCompCodeNames.VoidActionResultNameSpace));

    if (getBaseClassName().contains("bstractManagerAction")) {
      result.append(GetImportStr(JavaCompCodeNames.AbstractManagerActionNameSpace));
    }
    if (getBaseClassName().contains("RootAbstractAction")) {
      result.append(GetImportStr(JavaCompCodeNames.RootAbstractActionNameSpaceNameSpace));
    }
    //参数列表
    if (usingList == null || usingList.size() < 1) {
      return;
    }
    for (String usingName : usingList) {
      result.append(GetImportStr(usingName));
    }
  }

  protected boolean JavaHasCustomConstructorParams() {
    return parameters != null && parameters.size() >= 1;
  }

  protected void JavaGenerateConstructorParams(StringBuilder result) {

    for (int i = 0; i < parameters.size(); i++) {

      String parameterKey = (String) parameters.keySet().toArray()[i];

      ParameterInfo parameterValue = parameters.get(parameterKey);
      result.append(" ");
      if (!CheckInfoUtil.checkNull(parameterValue.getParameterMode())) {
        result.append(parameterValue.getParameterMode()).append(" ");
      }
      result.append(parameterValue.getParamType()).append(" ").append(parameterKey);
      if (i < parameters.size() - 1) {
        result.append(",");
      }

    }
  }

  protected void JavaGenerateConstructorContent(StringBuilder result) {
    if (parameters == null || parameters.size() < 1) {
      return;
    }

    for (Map.Entry<String, ParameterInfo> parameter : parameters.entrySet()) {
      result.append(GetIndentationStr()).append(GetIndentationStr()).append("this.")
          .append(parameter.getKey()).append(" = ").append(parameter.getKey()).append(";")
          .append(getNewline());

    }
  }


  ///#region Field
  @Override
  protected void JavaGenerateField(StringBuilder result) {
    if (parameters == null || parameters.size() < 1) {
      return;
    }

    for (Map.Entry<String, ParameterInfo> parameter : parameters.entrySet()) {
      result.append(getNewline()).append(GetIndentationStr())
          .append(JavaCompCodeNames.KeywordPrivate).append(" ")
          .append(parameter.getValue().getParamType()).append(" ").append(parameter.getKey())
          .append(";");

    }
  }

  ///#endregion

  private boolean JavaIsGeneric(IBizParameter param) {
    try {

//			var psn = Assembly.Load(param.getAssembly());
//			Class type = psn.GetType(param.getJavaClassName());
//			return type.IsGenericType;
      return true;
    } catch (Exception e) {
      //如果libs目录下如果未加载到程序集，默认其不是泛型类型
      return false;
    }


  }

  //把泛型参数类型涉及到的所有类型得到并存在List集合中
  private void JavaGetAllGenericParameterType(Class type) {
//		if (allGenericParamType.isEmpty())
//		{
//			allGenericParamType.add(type);
//		}
//		Class[] allType = type.GetGenericArguments();
//
//		for (Class t : allType)
//		{
//			allGenericParamType.add(t);
//			if (t.IsGenericType)
//			{
//				JavaGetAllGenericParameterType(t);
//			}
//		}

  }

  private void JavaAddUsing(String usingName) {
    if (CheckInfoUtil.checkNull(usingName)) {
      throw new RuntimeException("命名空间不能为空");
    }
    if (!CheckInfoUtil.checkNull(usingName) && !usingList.contains(usingName)) {
      usingList.add(usingName);
    }
  }

  private String JavaGetClassName(Class type) {
    if (Integer.class == type) {
      return "Integer";
    }
    if (String.class == type) {
      //return "string";
      return "String";
    }
    if (Boolean.class == type) {
      //return "bool";
      return "Boolean";
    }
    if (java.util.Date.class == type) {

      //return "DateTime";
      return "Date";
    }
    if (java.math.BigDecimal.class == type) {
      //return "decimal";
      return "BigDecimal";
    }
    if (Double.class == type) {
      return "Double";
    }
    if (Object.class == type) {
      //return "object";
      return "Object";
    }

    //string fullClassName = type.ToString().Split("`")[0];
    //string[] content = fullClassName.Split(".");
    String fullClassName = type.toString().split("[`]", -1)[0];
    String[] content = fullClassName.split("[.]", -1);
    return content[content.length - 1];


  }

  private String JavaGetGenericExpress(Class type) {
//		if (!type.IsGenericType)
//		{
//			return JavaGetClassName(type);
//		}
//		else
//		{
//			Class[] array = type.GenericTypeArguments;
//			int count = array.length;
//			String info = "{0}";
//			for (int i = 1; i < count; i++)
//			{
//				info = info + "," + "{" + i + "}";
//			}
//			info = JavaGetClassName(type) + "<" + inbfo + ">";
//			String[] arrayStr = new String[count];
//			for (int i = 0; i < count; i++)
//			{
//				arrayStr[i] = JavaGetGenericExpress(array[i]);
//			}
//			info = String.format(info, arrayStr);
//
//			return info;
//		}

    return null;

  }

  private void HandleJavaInfo(IBizParameter para) {
    if (CheckInfoUtil.checkNull(para.getClassName()) && !CheckInfoUtil
        .checkNull(((BizParameter) para).getNetClassName())) {
      //仅平台提供包，自动转Inspur.Gsp为com.inspur.edp
      if (para.getClassName().startsWith("Inspur.Gsp.")) {
        para.setClassName(HandleJavaClassName(((BizParameter) para).getNetClassName()));
      }
    }
  }

  private String HandleJavaClassName(String source) {
    if (CheckInfoUtil.checkNull(source)) {
      return source;
    }
    String result = "";
    String[] list = source.split("[.]", -1);
    for (int i = 0; i < list.length; i++) {
      String lowerCase = list[i].toLowerCase();
      if (i == 0 && lowerCase.equals("inspur")) {
        result = String.format("%1$s%2$s", result, "com.inspur");
        continue;
      }
      if (i == list.length - 1) {
        // 类名不需要转换为小写
        result = String.format("%1$s%2$s%3$s", result, ".", list[i]);
        continue;
      }
      result = String.format("%1$s%2$s%3$s", result, ".", lowerCase);
    }
    return result;
  }

}
